# app/services/family/account.py
from datetime import datetime, timedelta,time
from decimal import Decimal
from typing import List, Dict, Optional, Tuple
from tortoise.functions import Sum, Count
from tortoise.expressions import Q

from app.services.base.base_service import BaseService
from app.models.family.account import AccountRecord
from app.schemas.family.account import AccountCreate, AccountUpdate
from app.utils.app_log import logger
from app.core.exceptions import BusinessError
from app.schemas.base.error_code import *
from app.services.family.family_system import family_service
## 账单全部改好了 。。

class AccountService(BaseService):
    """家庭账本服务类，提供记账记录的增删改查及统计功能"""
    def __init__(self):
        super().__init__(model=AccountRecord, resource_name="账目记录")
        
    async def add_record(self, obj_in: AccountCreate) -> AccountRecord:
        """添加记账记录"""
        ## 注意 user_id，family_id
        try:
            # 使用基类的验证创建方法
            record = await self.validate_and_create(obj_in)
            logger.info(f"用户 {await self._get_current_user_id()} 添加账目记录: {obj_in}")
            return record
        
        except Exception as e:
            raise BusinessError(RESOURCE_CREATE_FAILED.format(resource="账目记录"),
                                details=f"""添加账目记录失败: {str(e)}""")

    async def update_record(self, record_id: int, obj_in: AccountUpdate) -> Optional[AccountRecord]:
        """更新记账记录"""
        try:
            # 直接使用基类的验证更新方法，里面会验证是否存在
            updated_record = await self.validate_and_update(record_id, obj_in)
            logger.info(f"用户 {await self._get_current_user_id()} 更新账目记录 {record_id}")
            return updated_record

        except Exception as e:
            # logger.error(f"更新账目记录失败: {str(e)}")
            raise BusinessError(RESOURCE_UPDATE_FAILED.format(resource="账目记录"),
                                details=f"""更新账目记录失败: {str(e)}""")

    async def delete_record(self, record_id: int) -> bool:
        """删除记账记录"""
        try:
            # 使用基类的安全获取方法验证权限
            record = await self.get_safe(record_id)
            if not record:
                raise BusinessError(RESOURCE_NOT_FOUND.format(resource="账目记录"),
                                details=f"""账目记录不存在 {record_id}""")
            
            # 使用基类的删除方法
            await self.remove(record_id)
            
            logger.info(f"用户 {await self._get_current_user_id()} 删除账目记录 {record_id}")
            return True
        
        except Exception as e:
            # logger.error(f"删除账目记录失败: {str(e)}")
            raise BusinessError(RESOURCE_DELETE_FAILED.format(resource="账目记录"),
                                details=f"""删除账目记录失败: {str(e)}""")

    async def list_by_user(
        self,
        page: int = 1,
        page_size: int = 10,
        search: Optional[str] = None,
        order: Optional[List[str]] = None
    ) -> Tuple[int, List[AccountRecord]]:
        """获取当前用户的账目记录列表"""
        try:
            # 构建查询条件
            q = Q()
            if search:
                q &= Q(description__contains=search) | Q(category__contains=search)
            
            # 使用基类的用户过滤方法
            user_filtered_q = await self._add_user_filter(q)
            
            return await self.list(page, page_size, user_filtered_q, order or ['-created_at'])
            
        except Exception as e:
            raise BusinessError(RESOURCE_NOT_FOUND.format(resource="账目记录列表"),
                                details=f"""获取账目记录列表失败: {str(e)}""")

    async def get_statistics(
        self,
        start_datetime: datetime,
        end_datetime: datetime
    ) -> Dict[str, str]:
        """获取指定时间范围的收入、支出和余额统计"""
                ## 关注 user_id
        end_datetime = datetime.combine(end_datetime, time.max) 
        try:
            if start_datetime > end_datetime:
                raise BusinessError(VALIDATION_ERROR,details=f"开始日期不能晚于结束日期")
            
            user_id = await self._get_current_user_id()
            logger.info(f"用户 {user_id} 获取分类统计数据")

            # 查询数据库
            query = self.model.filter(
                user_id=user_id,
                created_at__gte=start_datetime,
                created_at__lte=end_datetime,
                is_deleted=False
            ).group_by("type").annotate(total=Sum("amount")).values("type", "total")

            result = {item["type"]: item["total"] or Decimal('0') for item in await query}
     
            income = result.get('income', Decimal('0'))
            expense = result.get('expense', Decimal('0'))
            balance = income - expense

            return {
                "income": str(income),
                "expense": str(expense),
                "balance": str(balance),
                "income_formatted": f"¥{income:,.2f}",
                "expense_formatted": f"¥{expense:,.2f}",
                "balance_formatted": f"¥{balance:,.2f}"
            }
        except Exception as e:
            # logger.error(f"获取统计数据失败: {str(e)}")
            raise BusinessError(RESOURCE_NOT_FOUND.format(resource="账目统计数据"),
                                details=f"""获取统计数据失败: {str(e)}""")

    async def get_category_stats(
        self,
        start_datetime: datetime,
        end_datetime: datetime,
        type_: Optional[str] = None
    ) -> List[Dict[str, str]]:
        """获取指定时间范围和类型的分类统计"""
        ## 关注 user_id
        end_datetime = datetime.combine(end_datetime, time.max) 
        try:
            if start_datetime > end_datetime:
                raise BusinessError(VALIDATION_ERROR,details=f"开始日期不能晚于结束日期")

            user_id = await self._get_current_user_id()
            logger.info(f"用户 {user_id} 获取分类统计数据")

            # 构建查询
            query = self.model.filter(
                user_id=user_id,
                created_at__gte=start_datetime,
                created_at__lte=end_datetime,
                is_deleted=False,
            )

            if type_ in {'income', 'expense'}:
                query = query.filter(type=type_)

            result = await query.group_by("category").annotate(
                total=Sum("amount"),
                count=Count("id")
            ).values("category", "total", "count")

            data = [
                {
                    "category": item["category"],
                    "amount": str(item["total"] or Decimal('0')),
                    "amount_formatted": f"¥{item['total'] or 0:,.2f}",
                    "count": item["count"],
                    "percentage": 0  # 后续计算
                }
                for item in result
            ]
            
            # 计算百分比
            total_amount = sum(Decimal(item["amount"]) for item in data)
            if total_amount > 0:
                for item in data:
                    percentage = (Decimal(item["amount"]) / total_amount * 100)
                    item["percentage"] = float(percentage.quantize(Decimal('0.01')))
            
            # 按金额降序排列
            data.sort(key=lambda x: Decimal(x["amount"]), reverse=True)
            return data

        except Exception as e:
            # logger.error(f"获取分类统计失败: {str(e)}")
            raise BusinessError(RESOURCE_NOT_FOUND.format(resource="账目分类统计数据"),
                                details=f"""获取账目分类统计数据失败: {str(e)}""")

    async def get_monthly_trend(
        self,
        months: int = 12
    ) -> List[Dict[str, float]]:
        """获取月度趋势数据"""
        try:
            if months <= 0 or months > 24:
                raise BusinessError(VALIDATION_ERROR,f"""月份数量必须在1-24之间，当前为{months}""")

            user_id = await self._get_current_user_id()
            end_date = datetime.now()
            
            # 按月份统计
            monthly_stats = []
            for i in range(months):
                month_start = end_date.replace(day=1) - timedelta(days=i * 30)
                month_start = month_start.replace(day=1)
                month_end = (month_start + timedelta(days=32)).replace(day=1) - timedelta(days=1)
                
                stats = await self.get_statistics(month_start, month_end)
                
                monthly_stats.append({
                    "month": month_start.strftime("%Y-%m"),
                    "income": float(stats["income"]),
                    "expense": float(stats["expense"]),
                    "balance": float(stats["balance"])
                })
            
            return list(reversed(monthly_stats))
        
        except Exception as e:
            logger.error(f"获取月度趋势数据失败: {str(e)}")
            raise BusinessError(RESOURCE_NOT_FOUND.format(resource="账目月度趋势数据数据"),
                                details=f"""获取账目月度趋势数据数据失败: {str(e)}""")
        

account_service = AccountService()